#include "data_segment.h"
#include <spdlog/spdlog.h>
#include <string.h>
using namespace std;
using namespace safe_udp;

DataSegment::DataSegment() {
    ack_number_ = -1;
    seq_number_ = -1;
    length_ = -1;
}

DataSegment::~DataSegment() {
    if (final_packet_) {
        free(final_packet_);
        final_packet_ = nullptr;
    }
}

char* DataSegment::SerializeToCharArray() {
    if (final_packet_) {
        memset(final_packet_, 0, MAX_PACKET_SIZE);
    } else {
        final_packet_ = (char*)calloc(MAX_PACKET_SIZE, sizeof(char));
        if (final_packet_ == nullptr) {
            spdlog::error("dataSegment calloc failed");
            exit(1);
        }
    }
    memcpy(final_packet_, &seq_number_, sizeof(seq_number_));
    memcpy(final_packet_ + 4, &ack_number_, sizeof(ack_number_));
    memcpy(final_packet_ + 8, &ack_flag_, 1);
    memcpy(final_packet_ + 9, &fin_flag_, 1);
    memcpy(final_packet_ + 10, &length_, sizeof(length_));
    memcpy(final_packet_ + 12, data_, length_);

    return final_packet_;
}

void DataSegment::DeserializeToDataSegment(unsigned char* data_segment, int length) {
    seq_number_ = convert_to_uint32(data_segment, 0);
    ack_number_ = convert_to_uint32(data_segment, 4);
    ack_flag_ = conver_to_bool(data_segment, 8);
    fin_flag_ = conver_to_bool(data_segment, 9);
    length_ = convert_to_uint16(data_segment, 10);

    data_ = reinterpret_cast<char*>(calloc(length + 1, sizeof(char)));
    if (data_ == nullptr) {
        return;
    }
    memcpy(data_, data_segment + HEADER_LENGTH, length);
    *(data_ + length) = '\0';
}

uint32_t DataSegment::convert_to_uint32(unsigned char* buffer, int start_index) {
    uint32_t ret;
    memcpy(&ret, buffer + start_index, sizeof(ret));
    return ret;
}

bool DataSegment::conver_to_bool(unsigned char* buffer, int index) {
    bool ret;
    memcpy(&ret, buffer + index, sizeof(ret));
    return ret;
}

uint16_t DataSegment::convert_to_uint16(unsigned char* buffer, int start_index) {
    uint16_t ret;
    memcpy(&ret, buffer + start_index, sizeof(ret));

    return ret;
}